/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package net.flowas.genericcrud.service;

import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.PathParam;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import net.flowas.genericcrud.ResourceRegister;
import net.flowas.genericcrud.service.chain.I18nRegister;
import net.flowas.genericcrud.service.impl.CommonFunction;
import net.flowas.genericcrud.service.impl.RequestDispatcher;

/**
 * 页面的显示配置.
 * 
 * @author Administrator
 */
public class ViewConfig implements ResourceRegister {
	private static final Logger LOG = LoggerFactory.getLogger(ViewConfig.class);
	private static final String UI_SETTINGS_FILE = "META-INF/uiSettings.xml";
	private final Map<String, String> sortOrder = new HashMap<>();
	private final Map<String, List> columnDefs = new HashMap<>();
	private boolean defualtLoaded = false;
	private RequestDispatcher facade;
	private I18nRegister i18nRegister;

	public void setI18nRegister(I18nRegister i18nRegister) {
		this.i18nRegister = i18nRegister;
	}

	public void setFacade(RequestDispatcher facade) {
		this.facade = facade;
	}

	/**
	 * 获取模型数据的排序语句，用在sql查询order by子句中.
	 * 
	 * @param type 模型数据类型
	 */
	public String sortOrder(Class type) {
		if (!sortOrder.containsKey(type.getSimpleName()) && !columnDefs.containsKey(type.getSimpleName())) {
			initViewConfig();
		}
		return sortOrder.get(type.getSimpleName());
	}

	/**
	 * 获取模型的字段定义国际化名称.
	 * 
	 * @param modelName 模型数据类型
	 */
	public List<Map<String, Object>> columnDefs(@PathParam("modelType") String modelName) {
		if (!columnDefs.containsKey(modelName)) {
			initViewConfig();
		}
		return columnDefs.get(modelName);
	}

	public void initViewConfig() {
		if (defualtLoaded) {
			return;
		}
		URL url = ViewConfig.class.getClassLoader().getResource(UI_SETTINGS_FILE);
		if (url == null) {
			LOG.warn("can not find UI_SETTINGS file:[" + UI_SETTINGS_FILE + "]");
		} else {
			addResource(url, null);
		}
		defualtLoaded = true;
	}

	private void parceModel(Element model, String modelName) {
		if (model != null) {
			List<Map<String, String>> columns = new ArrayList<>();
			NodeList nodes = model.getElementsByTagName("field");
			for (int i = 0; i < nodes.getLength(); i++) {
				Element field = (Element) nodes.item(i);
				Map<String, String> fieldDef = new HashMap<>();
				String name = field.getAttribute("name");
				String displayName = field.getAttribute("displayName");
				fieldDef.put("field", name);
				if (displayName == null || "".equals(displayName)) {
					String key = name;
					if (name.contains(".")) {
						String[] frags = name.split("\\.");
						key = frags[frags.length - 1];
					}
					displayName = i18nRegister.get(key);
				}
				fieldDef.put("displayName", displayName);
				String formType = field.getAttribute("formType");
				if (formType != null && !"".equals(formType)) {
					fieldDef.put("formType", formType);
				}
				columns.add(fieldDef);
			}
			NodeList orderBy = model.getElementsByTagName("orderBy");
			if (orderBy.getLength() > 0) {
				sortOrder.put(modelName, orderBy.item(0).getTextContent());
			}
			columnDefs.put(modelName, columns);
		}
	}

	/**
	 * 从url中读取配置文件，并解析为ui字段配置.
	 * 
	 * @param url 配置文件位置
	 */
	@Override
	public void addResource(URL url, ClassLoader classLoader) {
		NodeList models = CommonFunction.parceXmlConfig(url).getElementsByTagName("model");
		for (int i = 0; i < models.getLength(); i++) {
			Element model = (Element) models.item(i);
			String modelName = model.getAttribute("name");
			parceModel(model, modelName);
		}
		// 每次添加url都会重新计算一次
		Map<String, Class> types = facade.getTypeMaps();
		for (String modelType : types.keySet()) {
			if (columnDefs.containsKey(modelType)) {
				continue;
			}
			List<Map<String, String>> columns = new ArrayList<>();
			Class clasz = types.get(modelType);
			for (Field field : clasz.getDeclaredFields()) {
				String name = field.getName();
				String displayName = name;
				// String formType =
				Map<String, String> fieldDef = new HashMap<>();
				fieldDef.put("field", name);
				fieldDef.put("displayName", displayName);
				columns.add(fieldDef);
			}
			columnDefs.put(modelType, columns);
		}
	}

	/**
	 * 销毁注册信息.
	 * 
	 * @param url 配置文件位置
	 */
	@Override
	public void removeResource(URL url) {
		NodeList models = CommonFunction.parceXmlConfig(url).getElementsByTagName("model");
		for (int i = 0; i < models.getLength(); i++) {
			Element model = (Element) models.item(i);
			columnDefs.remove(model.getAttribute("name"));
		}
	}

	public Map<String, String> i18nToMap() {
		return i18nRegister.i18nToMap();
	}

}
